package gui;

import gui.charts.Chart;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import data.EffortProvider;
import data.ProjectDataProvider;
import data.model.ProjectCharacteristics;
import data.model.ProjectWeek;
import data.model.effort.CurrentEffort;

public class ProjectDataComposite extends Composite implements
		PropertyChangeListener {
	private final DataBindingContext m_bindingContext;
	private final Table tableEffort;
	private final ProjectDataProvider projectDataProvider;
	private final TableViewer tableViewerEffort;
	private final Canvas canvasEffort;
	private final Canvas canvasCharacs;

	/**
	 * Create the composite.
	 * 
	 * @param parent
	 * @param style
	 */
	public ProjectDataComposite(Composite parent, int style,
			ProjectDataProvider projectDataProvider,
			ProjectCharacteristics projectHealthCriteria) {
		super(parent, style);
		setLayout(new GridLayout(2, false));

		this.projectDataProvider = projectDataProvider;

		canvasCharacs = new Canvas(this, SWT.NONE);
		GridData gd_canvasCharacs = new GridData(SWT.LEFT, SWT.TOP, false,
				false, 1, 1);
		gd_canvasCharacs.heightHint = 312;
		gd_canvasCharacs.widthHint = 439;
		canvasCharacs.setLayoutData(gd_canvasCharacs);

		canvasCharacs.addPaintListener(new PaintListener() {
			@Override
			public void paintControl(PaintEvent e) {
				Image image = null;
				try {
					image = Chart.getXYChart("Project Characteristics",
							ProjectDataComposite.this.projectDataProvider
									.getProjectWeeks());
					canvasCharacs.setSize(image.getImageData().width,
							image.getImageData().height);
				} catch (Exception e1) {
					e1.printStackTrace();
				}

				e.gc.drawImage(image, 0, 0);

				image.dispose();
			}
		});
		canvasEffort = new Canvas(this, SWT.NONE);
		canvasEffort.setLayout(new FillLayout(SWT.HORIZONTAL));
		GridData gd_canvasEffort = new GridData(SWT.LEFT, SWT.TOP, false,
				false, 1, 1);
		gd_canvasEffort.heightHint = 312;
		gd_canvasEffort.widthHint = 450;
		canvasEffort.setLayoutData(gd_canvasEffort);

		canvasEffort.addPaintListener(new PaintListener() {
			@Override
			public void paintControl(PaintEvent e) {
				Image image = null;
				try {
					image = Chart.getPieChart(
							"Current Effort Data [person hours]",
							ProjectDataComposite.this.projectDataProvider
									.getCurrentEffort());
				} catch (Exception e1) {
					e1.printStackTrace();
				}

				e.gc.drawImage(image, 0, 0);

				image.dispose();
			}
		});

		Composite productCharacteristicsComposite = new ProjectCharacteristicsComposite(
				this, SWT.NONE, projectDataProvider, projectHealthCriteria);
		productCharacteristicsComposite.setLayoutData(new GridData(SWT.CENTER,
				SWT.TOP, false, false, 1, 1));

		tableViewerEffort = new TableViewer(this, SWT.BORDER
				| SWT.FULL_SELECTION);
		tableEffort = tableViewerEffort.getTable();
		tableEffort.setHeaderVisible(true);
		GridData gd_tableEffort = new GridData(SWT.LEFT, SWT.TOP, true, true,
				1, 1);
		gd_tableEffort.minimumWidth = 400;
		tableEffort.setLayoutData(gd_tableEffort);

		TableViewerColumn tableViewerColumnTitel = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnTitel = tableViewerColumnTitel.getColumn();
		tblclmnTitel.setWidth(75);

		TableViewerColumn tableViewerColumnRequirementsEngineering = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnRequirementsEngineering = tableViewerColumnRequirementsEngineering
				.getColumn();
		tblclmnRequirementsEngineering
				.setToolTipText("Requirement Engineering");
		tblclmnRequirementsEngineering.setWidth(50);
		tblclmnRequirementsEngineering.setText("RE");

		TableViewerColumn tableViewerColumnArchitectureAndDesign = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnArchitectureAndDesign = tableViewerColumnArchitectureAndDesign
				.getColumn();
		tblclmnArchitectureAndDesign.setToolTipText("Architecture and Design");
		tblclmnArchitectureAndDesign.setWidth(50);
		tblclmnArchitectureAndDesign.setText("AD");

		TableViewerColumn tableViewerColumnImplementationAndIntegration = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnImplementationAndIntegration = tableViewerColumnImplementationAndIntegration
				.getColumn();
		tblclmnImplementationAndIntegration
				.setToolTipText("Implementation and Integration");
		tblclmnImplementationAndIntegration.setWidth(50);
		tblclmnImplementationAndIntegration.setText("II");

		TableViewerColumn tableViewerColumnBuildAndTest = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnBuildAndTest = tableViewerColumnBuildAndTest
				.getColumn();
		tblclmnBuildAndTest.setToolTipText("Build and Test");
		tblclmnBuildAndTest.setWidth(50);
		tblclmnBuildAndTest.setText("BT");

		TableViewerColumn tableViewerColumnProjectManagement = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnProjectManagement = tableViewerColumnProjectManagement
				.getColumn();
		tblclmnProjectManagement.setToolTipText("Project Management");
		tblclmnProjectManagement.setWidth(50);
		tblclmnProjectManagement.setText("PM");

		TableViewerColumn tableViewerColumn = new TableViewerColumn(
				tableViewerEffort, SWT.NONE);
		TableColumn tblclmnTotal = tableViewerColumn.getColumn();
		tblclmnTotal.setWidth(50);
		tblclmnTotal.setText("Total");

		this.projectDataProvider.getCurrentEffort().addPropertyChangeListener(
				this);

		m_bindingContext = initDataBindings();
	}

	private ArrayList<EffortProvider> getEffortProvidersAsSet() {
		ArrayList<EffortProvider> effortProviders = new ArrayList<EffortProvider>();

		if (projectDataProvider instanceof ProjectWeek) {
			// delta values
			effortProviders.add(((ProjectWeek) projectDataProvider)
					.getDeltaEffort());
		}
		// current values
		effortProviders.add(projectDataProvider.getCurrentEffort());
		// estimated values
		effortProviders.add(projectDataProvider.getEstimatedEffort());

		return effortProviders;
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
		tableViewerEffort.setContentProvider(listContentProvider);
		//
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				listContentProvider.getKnownElements(), EffortProvider.class,
				new String[] { "text", "effortRequirementsEngineering",
						"effortArchitectureAndDesign",
						"effortImplementationAndIntegration",
						"effortBuildAndTest", "effortProjectManagement",
						"effort" });
		tableViewerEffort.setLabelProvider(new ObservableMapLabelProvider(
				observeMaps));
		//
		WritableList writableList = new WritableList(getEffortProvidersAsSet(),
				CurrentEffort.class);
		tableViewerEffort.setInput(writableList);
		//
		return bindingContext;
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		canvasEffort.addPaintListener(new PaintListener() {
			@Override
			public void paintControl(PaintEvent e) {
				Image image = null;
				try {
					image = Chart.getPieChart(
							"Current Effort Data [person hours]",
							ProjectDataComposite.this.projectDataProvider
									.getCurrentEffort());
				} catch (Exception e1) {
					e1.printStackTrace();
				}

				e.gc.drawImage(image, 0, 0);

				image.dispose();
			}
		});
		canvasEffort.redraw();
	}
}
